#include "ThreadPool.h"
#include <cstddef>
#include <functional>
#include <mutex>
#include <stdexcept>
#include <utility>
ThreadPool::ThreadPool(size_t numThreads)
    : m_numThreads(numThreads ? numThreads : 1), m_running(true),
      m_free_thread_num(m_numThreads) {
  for (int i = 0; i < m_numThreads; ++i) {
    m_threads.emplace_back(&ThreadPool::worker, this);
  }
}

ThreadPool::~ThreadPool() {
  stop();
  for (size_t i = 0; i < m_numThreads; ++i) {
    if (m_threads[i].joinable()) {
      m_threads[i].join();
    }
  }
}

void ThreadPool::worker() {
  std::function<void()> task;
  while (1) {
    {
      std::unique_lock<std::mutex> lock(m_mutex);
      // 等待任务队列不为空 或 线程池停止
      task_condition.wait(
          lock, [this]() { return !m_tasks.empty() || !m_running.load(); });
      if (!m_running.load()) {
        return;
      }
      m_free_thread_num--;
      // 取出一个任务执行
      task = std::move(m_tasks.front());
      m_tasks.pop();
    }
    // 执行任务
    task();
    m_free_thread_num++;
    {
      std::unique_lock<std::mutex> lock(m_mutex);
      free_thread_cond.notify_one();
    }
  }
}

// 停止线程池
void ThreadPool::stop() {
  m_running = false;
  task_condition.notify_all();
}
// 线程池是否运行
bool ThreadPool::isRunning() const { return m_running.load(); }
// 任务队列大小
size_t ThreadPool::queueSize() const {
  std::lock_guard<std::mutex> lock(m_mutex);
  return m_tasks.size();
}
// 工作线程数量
size_t ThreadPool::threadCount() const { return m_numThreads; }
// 等待所有任务完成
void ThreadPool::waitForAllTasks() {
  // 任务队列为空 且 每个线程均停止运行
  std::unique_lock<std::mutex> lock(m_mutex);
  free_thread_cond.wait(lock, [this]() {
    return m_tasks.empty() && (m_free_thread_num == m_numThreads);
  });
}
// 清空任务队列
void ThreadPool::clearTasks() {
  {
    std::unique_lock<std::mutex> lock(m_mutex);
    while (!m_tasks.empty()) {
      m_tasks.pop();
    }
  }
  free_thread_cond.notify_all();
}